#include "gpio.h"
#include "common.h"
#include "init.h"
#include <linux/gpio.h>
#include <linux/slab.h>

struct gpio_cfg {
	struct init_block init;
	unsigned id;
	bool success;
};

static int gpio_init(struct init_block *init);
static void gpio_cleanup(struct init_block *init);
static void gpio_drop(struct init_block *init);

int request_gpio(unsigned gpio_id, const char *gpio_name) 
{
	struct gpio_cfg *cfg = kmalloc(sizeof(struct gpio_cfg), GFP_KERNEL);

	cfg->init.init_fn = gpio_init;
	cfg->init.cleanup_fn = gpio_cleanup;
	cfg->init.drop_fn = gpio_drop;
	cfg->id = gpio_id;
	cfg->success = false;
	strlcpy(cfg->init.name, gpio_name, BLOCK_NAME_LEN);

	PR_INFO("try request gpio (%d, %s)", cfg->id, cfg->init.name);

	return try_init(&cfg->init);
}

int gpio_init(struct init_block *init)
{
	int ret = 0;
	struct gpio_cfg *cfg = container_of(
			init, 
			struct gpio_cfg, 
			init
	);	
	ret = gpio_request(cfg->id, init->name);
	if (ret < 0) {
		PR_ERR("gpio_request (%d, %s) failed: %d", cfg->id, init->name, ret);
		cfg->success = false;
	} else {
		cfg->success = true;
	}
	return ret;
}


void gpio_cleanup(struct init_block *init)
{
	struct gpio_cfg *cfg = container_of(
			init, 
			struct gpio_cfg, 
			init
	);

	if (cfg->success) {
		PR_INFO("free gpio requested: (%d, %s)", cfg->id, init->name);
		gpio_free(cfg->id);
	}
}

void gpio_drop(struct init_block *init)
{

	struct gpio_cfg *cfg = container_of(
			init, 
			struct gpio_cfg, 
			init
	);
	kfree(cfg);
}



